package shareTxt;

import java.io.*;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.util.Random;

public class producer {
//Peterson法实现临界区互斥
    public static void main(String[] args) throws Exception {
        int size = 0x4;  //映射字节缓冲区长度
        int position = 0; //共享空间起始位置
        int proLock = 0; //内存第0号位作为生产者标志位
        int conLock = 1; //第1位作为消费者标志位
        int ban = 2; //第2位作为禁止位
        int buf = 3; //第3位存储缓冲区大小
        byte in = 1; //1代表进入
        byte out = 0; //0代表不进入
        byte ban_con= -1; //禁止位为-1代表禁止消费者进入
        int tt=0; //记录总生产数量

        String shareFileName="data.txt";  //共享文件路径，使用txt文件为媒介
        //开辟映射字节缓冲区，对象名为mapBuf，把文件的从position开始的size大小的区域映射为MappedByteBuffer
        MappedByteBuffer mapBuf = new RandomAccessFile(shareFileName, "rw")
                .getChannel().map(FileChannel.MapMode.READ_WRITE, position, size);

        //初始化缓冲区,第0位存储生产者标志，第1位存储消费者标志，第2位存储禁止标志，第3位存当前储缓冲池大小
        for (int i = 0; i <size; mapBuf.put(i, (byte)0),i++);

        while(true){
            int temp =0;
            Thread.sleep(new Random().nextInt(1000)); //此处sleep调整整体运行的速度
            mapBuf.put(proLock,in); //经典Peterson法：双标志位加禁止位
            mapBuf.put(ban,ban_con);
            //若消费者占用临界则等待
            while (mapBuf.get(conLock) == in && mapBuf.get(ban) == ban_con){
                if(temp==0){System.out.println("消费者正在访问资源，生产者等待");temp=1;}
            }

            mapBuf.put(proLock,in);
            Thread.sleep(new Random().nextInt(200)); //此处sleep增加资源冲突的概率，利于展示实验结果
            int buffer = mapBuf.get(buf); //获取资源数量
            if(buffer == 2){ //缓冲池资源数量上限为2
                System.out.println("仓库满了！停止生产！");
            }
            else{
                buffer++; //生产资源
                tt++;
                System.out.println("生产一个资源，当前库存"+buffer+"个，总共已生产"+tt+"个资源");
                mapBuf.put(buf,(byte)buffer);  //释放锁之前将数据写回
            }

            mapBuf.put(proLock,out); //退出临界
        }
    }
}
